#include "iotgo_platformAPI.h"
#include "iotgo_debug.h"
#include "iotgo_memory_hooks.h"

#include "iotgo_communicate_with_distribute_server.h"
#include "iotgo_communicate_with_long_server.h"
#include "iotgo_service.h"
#include "iotgo_pair_with_app.h"

#define debugPrint serviceDebugPrint

#define NO_PAIRING_NOW       0
#define GET_READY_FOR_PAIRING 1
#define READY_FOR_PAIRING     2

static volatile int iotgo_state = IOTGO_IDLE;

static volatile int pair_with_app_flag = NO_PAIRING_NOW;

static int connectWifi(void)
{
    int8_t ret = -1;
    uint8_t wifi_ssid[STRING_WIFI_SSID_LEN] = {0};
    uint8_t wifi_password[STRING_WIFI_PASSWORD_LEN] = {0};
    getConnectWifiInfo(wifi_ssid,wifi_password);
    ret = connectToWifi(wifi_ssid,wifi_password);
    return ret;
}

int iotgoDataServiceRuntime(void)
{
    int32_t ret = -1;

    switch(iotgo_state)
    {
    case IOTGO_IDLE:
        print_memory_heap();
        ret = connectWifi();
        if(ret == 0)
        {
            iotgo_state = IOTGO_AP_IS_CONNECTED;
            ret = IOTGO_ERROR_NONE;
        }
        ret = IOTGO_ERROR_WIFI_CONNECT;
        print_memory_heap();
        break;
    case IOTGO_AP_IS_CONNECTED:
        /* connect to Dserver */
        print_memory_heap();
        ret = communicateWithDistrServer();
        debugPrint("[%s]DistrServer return is %d\n",__FUNCTION__,ret);
        if(ret < DSERVER_ERROR_NOT_FINISHED)
        {       
            if(pair_with_app_flag == NO_PAIRING_NOW)
            {
                iotgo_state = IOTGO_IDLE;
                cleanWithDistrServer();
            }
            debugPrint("[%s]error with distribute server\n",__FUNCTION__);
            return IOTGO_ERROR_DSERVER_DISCONNECTED;
        }
        ret = getStateWithDistrServer();
        debugPrint("[%s]DistrServer state : %d\n",__FUNCTION__,ret);
        if(ret == DSERVER_QUERY_IS_DONE)
        {
            debugPrint("[%s]distribute server query is done\n",__FUNCTION__);
            cleanWithDistrServer();
            iotgo_state = IOTGO_DSERVER_IS_CONNECTED;
            print_memory_heap();
        }
        ret = IOTGO_ERROR_NONE;
        break;
    case IOTGO_DSERVER_IS_CONNECTED:
    case IOTGO_LSERVER_IS_CONNECTED:
    case IOTGO_REGISTER_IS_READY:
    case IOTGO_UPGRADE:
        print_memory_heap();
        /* connect to Lserver */
        ret = communicateWithLongServer();
        debugPrint("[%s]communicateWithLongServer return is %d\n",__FUNCTION__,ret);
        print_memory_heap();
        if(ret < LSERVER_ERROR_NOT_FINISHED)
        {       
            if(pair_with_app_flag == NO_PAIRING_NOW)
            {
                iotgo_state = IOTGO_IDLE;
                cleanWithLongServer();
            }
            debugPrint("[%s]error with long server\n",__FUNCTION__);
            return IOTGO_ERROR_LSERVER_DISCONNECTED;
        }
        ret = getStateWithLongServer();
        if(ret == LSERVER_SOCKET_IS_READY)
        {
            debugPrint("[%s]check lserver state : socket is done\n",__FUNCTION__);
            iotgo_state = IOTGO_LSERVER_IS_CONNECTED;
        }
        else if(ret == LSERVER_REGISTER_IS_READY)
        {
            debugPrint("[%s]check lserver state : register is done\n",__FUNCTION__);
            iotgo_state = IOTGO_REGISTER_IS_READY;
        }
        ret = IOTGO_ERROR_NONE;
        break;
    case IOTGO_PAIR_WITH_APP:
	if(pair_with_app_flag < READY_FOR_PAIRING)
	{
            ret = IOTGO_ERROR_PAIR_NOT_FINISHED;
	}

        ret = pairWithAppRunTime();
        if(ret == PAIR_SUCCESS)
        {
            ret = IOTGO_ERROR_NONE;
            iotgoPairWithAppStop();
        }
        else
        {
            ret = IOTGO_ERROR_PAIR_NOT_FINISHED;
        }
    
    default:
        ret = IOTGO_ERROR_NONE;
        break;
    }
    /* inner delay*/
    if(iotgo_state != IOTGO_REGISTER_IS_READY && iotgo_state != IOTGO_PAIR_WITH_APP)
    {
	systemDelayMs(100);
    }
    else if(iotgo_state == IOTGO_PAIR_WITH_APP)
    {
	//systemDelayMs(1);
    }
    return ret;
}

int iotgoDataServiceClean()
{
    cleanWithLongServer();
    cleanWithDistrServer();
    cleanPairWithApp();
    iotgo_state = IOTGO_IDLE;
    return 0;
}

int iotgoPairWithAppStart(void)
{
    debugPrint("[%s]iotgoPairWithAppStart\n",__FUNCTION__);
    if(iotgo_state < IOTGO_PAIR_WITH_APP)
    {
        debugPrint("[%s] iotgo state change to IOTGO_PAIR_WITH_APP\n",__FUNCTION__);
        iotgo_state = IOTGO_PAIR_WITH_APP;
        pair_with_app_flag = GET_READY_FOR_PAIRING;
        cleanWithLongServer();
        cleanWithDistrServer();
        pair_with_app_flag = READY_FOR_PAIRING;
        debugPrint("[%s] ready for pairing\n",__FUNCTION__);
        return IOTGO_ERROR_NONE;
    }
    return IOTGO_ERROR_FORBID;
}

int iotgoPairWithAppStop(void)
{
    if(iotgo_state == IOTGO_PAIR_WITH_APP)
    {
        debugPrint("[%s] start to cleanPairWithApp\n",__FUNCTION__);
        cleanPairWithApp();
        debugPrint("[%s] change iotgo_state to IOTGO_IDLE\n",__FUNCTION__);
        iotgo_state = IOTGO_IDLE;
        pair_with_app_flag = NO_PAIRING_NOW;
        return IOTGO_ERROR_NONE;
    }
    return IOTGO_ERROR_FORBID;
}

int iotgoGetState(void)
{
    return iotgo_state;
}

int32_t iotgoWriteErrorNumToServer(uint32_t num, uint8_t *sequence)
{
    int ret = -1;

    if(iotgo_state == IOTGO_REGISTER_IS_READY)
    {
	if(strncmp(sequence,"devConfig",9) == 0)
	{
	    return 0;
	}
	ret = writeErrorNumToServer(num,sequence);
    }

    return ret;
}

int32_t iotgoWriteUpdateToServer(uint8_t *params)
{
    int ret = -1;

    if(iotgo_state == IOTGO_REGISTER_IS_READY)
    {
	ret = writeUpdateToServer(params);
    }

    return ret;
}

int32_t iotgoWriteQueryToServer(uint8_t *params)
{
    int ret = -1;

    if(iotgo_state == IOTGO_REGISTER_IS_READY)
    {
	ret = writeQueryToServer(params);
    }
    return ret;
}

int32_t iotgoWriteDateQueryToServer(void)
{
    int ret = -1;

    if(iotgo_state == IOTGO_REGISTER_IS_READY)
    {
	ret = writeDateQueryToServer();
    }
    return ret;
}

int32_t iotgoReadByDataType(uint8_t type, uint8_t *sequence, uint8_t *params)
{
    int32_t ret = -1;

    if(iotgo_state == IOTGO_REGISTER_IS_READY)
    {
	ret = readFromServerByIotgoType(type,sequence,params);
    }
    //debugPrint("[whReadByDataType] readFromServerByIotgoType ret is %d\n",ret);
    return ret;
}

int32_t iotgoReadUserApiKey(uint8_t *user_api_key)
{
    getUserApikey(user_api_key);
    return 0;
}


int iotgoUpgrade(uint8_t *sequence,uint8_t *params)
{
  
#if 0
    int count = 0;
    int ret = -1;

    //ret = parseUpgradeMessage(params);
    //if(ret == 0)
    //{
        //debugPrint("parseUpgradeMessge is done\n");
        iotgo_state = IOTGO_UPGRADE;
        startUpgradetask();
        while(1)
        {
            ret = isUpgradeDone();
            if(ret == 0)
            {
                iotgoWriteErrorNumToServer(0, sequence);
                platformReset();
            }
            count++;
            if(count == 30)//fail
            {
                iotgoWriteErrorNumToServer(400, sequence);
                RtlMsleepOS(1000);
                platformReset();
                break;
            }

            RtlMsleepOS(1000);
        }
    }
    //else
    //{
      //  iotgoWriteErrorNumToServer(400, sequence);
    //}

    iotgo_state = IOTGO_UPGRADE;
    startUpgradetask();
#endif
    return 0;
}




